###
  THE G1BC ENGINE | MAIN MODULE
  ----------------|------------
  This controls the other modules (generator, textures) and contains
  the code to draw/move/resize shapes on the canvas

  Thanks to Simon - http://simonsarris.com/project/canvasdemo/shapes.html for
  providing the tutorial teaching us how to drag canvas shapes around
###

class EditableShape
  constructor: (@x, @y, @w, @h, @fill) ->

  draw: (ctx) ->
    ctx.fillStyle = @fill
    ctx.fillRect(@x, @y, @w, @h)

  contains: (mx, my) ->
    if (@x <= mx) and (@x + @w >= mx) and (@y <= my) and (@y + @h >= my) then true else false

class CanvasState
  constructor: (@canvas) ->
    @width = @canvas.width
    @height = @canvas.height
    @ctx = @canvas.getContext('2d')

    #Fixes mouse coords problems with the red border
    if document.defaultView and document.defaultView.getComputedStyle
      @stylePaddingLeft = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingLeft'], 10)      || 0
      @stylePaddingTop  = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingTop'], 10)       || 0
      @styleBorderLeft  = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderLeftWidth'], 10)  || 0
      @styleBorderTop   = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderTopWidth'], 10)   || 0

    #State
    @valid = no;
    @shapes = [];
    @dragging = no;
    @selection = null;
    @dragoffx = 0;
    @dragoffy = 0;

    myState = this

    #fixes text selection problems
    canvas.addEventListener 'selectstart',
      (e) ->
        e.preventDefault()
        false
      false

    #the mighty dragger
    canvas.addEventListener 'mousedown',
      (e) ->
        mouse = myState.getMouse(e)
        mx = mouse.x
        my = mouse.y
        shapes = myState.shapes
        l = shapes.length

        `for (var i = l-1; i >= 0; i--) {
          if (shapes[i].contains(mx, my)) {
            var mySel = shapes[i];
            myState.dragoffx = mx - mySel.x;
            myState.dragoffy = my - mySel.y;
            myState.dragging = true;
            myState.selection = mySel;
            myState.valid = false;
            return;
          }
        }`

        if myState.selection
          myState.selection = null
          myState.valid = no
      true

    canvas.addEventListener 'mousemove',
      (e) ->
        if myState.dragging
          mouse = myState.getMouse(e)

          myState.selection.x = mouse.x - myState.dragoffx
          myState.selection.y = mouse.y - myState.dragoffy

          myState.valid = no
      true

    canvas.addEventListener 'mouseup',
      (e) ->
        myState.dragging = no
      true

    canvas.addEventListener 'dblclick',
      (e) ->
        mouse = myState.getMouse(e)

        myState.addShape(new EditableShape(mouse.x - 10, mouse.y - 10, 20, 20, 'rgba(0,255,0,.6)'))
      true

    @selectionColour = '#cc0000'
    @selectionWidth = 2
    @interval = 30
    setInterval(
      ->
        myState.draw
      myState.interval
    )

  addShape: (shape) ->
    @shapes.push(shape)
    @valid = no

  clear: ->
    @ctx.clearRect(0, 0, @width, @height);

  draw: ->
    if not @valid
      ctx = @ctx
      shapes = @shapes
      @clear()

      ## Stuff drawn in the background all the time

      for shape in shapes
        if shape.x > this.width or shape.y > this.height or shape.x + shape.w < 0 or shape.y + shape.h < 0 then continue
        shape.draw(ctx)

      #selection
      if @selection isnt null
        ctx.strokeStyle = this.selectionColor
        ctx.lineWidth = this.selectionWidth
        mySel = @selection;
        ctx.strokeRect mySel.x,mySel.y,mySel.w,mySel.h

      this.valid = yes

  getMouse: (e) ->
    element = `this.canvas, offsetX = 0, offsetY = 0, mx, my`

    if element.offsetParent isnt undefined
      while element = element.offsetParent
        offsetY += element.offsetLeft
        offsetX += element.offsetTop

    offsetX += this.stylePaddingLeft + this.styleBorderLeft + this.htmlLeft
    offsetY += this.stylePaddingTop + this.styleBorderTop + this.htmlTop

    mx = e.pageX - offsetX
    my = e.pageY - offsetY

    return {x: mx, y: my};

init = ->
  s = new CanvasState(document.getElementById('canvas'));
  s.addShape(new Shape(40,40,50,50));
